
`include "common_header.verilog"

//  *************************************************************************
//  File : mtip_top_10_40_mac_pcs
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2011 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//  Description : Top-Level
//  *************************************************************************

module mtip_top_10_40_mac_pcs (

// Common Reset Signal
// -------------------

   reset_reg_clk,

// MAC Reset Signals
// -----------------

   mac_reset_ref_clk,
   mac_reset_ff_rx_clk,
   mac_reset_ff_tx_clk,
   
// 40Geth PCS Reset Signals
// ------------------------

   xlaui_reset_rx_clk,
   xlaui_reset_tx_clk,
   xlaui_reset_ref_clk,

// 10Geth PCS Reset Signals
// ------------------------

   xaui_reset_rx_clk,
   xaui_reset_tx_clk,

// Common Clock Signals
// --------------------

   reg_clk,
   ref_clk,
   rx_clk,
   tx_clk,
   ff_rx_clk,
   ff_tx_clk,
   
// Serdes Interface
// ----------------

   sd0_rx,
   sd1_rx,
   sd2_rx,
   sd3_rx,
   sd0_tx,
   sd1_tx,
   sd2_tx,
   sd3_tx,  
   sd_signal, 
   
// Client Interface
// ----------------

   axi_ttvalid,
   axi_ttlast,
   axi_ttkeep,
   axi_ttdata,
   axi_ttuser, 
   axi_ttready,
   axi_rtvalid,
   axi_rtlast,
   axi_rtkeep,
   axi_rtdata,
   axi_rtuser,
   axi_rtready,
   tx_ovr_err,
   tx_underflow,
   tx_empty,
   ff_rx_empty,
    
// Mode Selection
// --------------

   ena_40g,
   jumbo_en,

// MAC Command and Control
// -----------------------

   lpi_txhold,
   loc_fault,
   rem_fault,
   li_fault,
   tx_loc_fault,
   tx_rem_fault,
   tx_li_fault,
   phy_txena,
   loop_ena,
   pfc_mode,
   pause_on,
   xoff_gen,

// Timestamping Control
// --------------------

   tx_sfd_o,
   frc_in_tx,
   rx_sfd_o,
   frc_in_rx,
   xgmii_rx_sop_shift,
   xgmii_tx_sop_shift,
   
// Timestamp Return Interface
// --------------------------

   tx_ts_val,
   tx_ts,
   tx_ts_id,
   tx_ts_frm_out,

// XAUI PCS Status
// ---------------

   x_align_done,
   x_disp_err,
   x_char_err,
   x_cg_align,
   x_sync,
   x_pat,
   
// XLAUI PCS Status
// ----------------

   xl_ber_timer_done,
   xl_block_lock,
   xl_align_done,
   xl_hi_ber,

// MAC Register Interface
// ----------------------

   regm_rden,
   regm_wren,
   regm_addr,
   regm_din,
   regm_dout,
   regm_busy,
   regm_ts_avail,
   regm_lowp,
   regm_lowp_ena,
      
// 40Geth PCS Register Interface
// -----------------------------

   regxl_rden,
   regxl_wren,
   regxl_addr,
   regxl_din,
   regxl_dout,
   regxl_busy,

// 10Geth PCS Register Interface
// -----------------------------

   regx_rden,
   regx_wren,
   regx_addr,
   regx_din,
   regx_dout,
   regx_busy,

//  MDIO Master
//  -----------

   mdc,
   mdio_in,
   mdio_out,
   mdio_oen, 
   
//  Memory Interfaces
//  -----------------

   rstm_raddr,
   rstm_rden,
   rstm_rdata,
   rstm_wren,
   rstm_waddr,
   rstm_wdata,
   tstm_raddr,
   tstm_rden,
   tstm_rdata,
   tstm_wren,
   tstm_waddr,
   tstm_wdata,
   rxd_raddr,
   rxd_rden,
   rxd_rdata,
   rxd_recc,
   rxd_wren,
   rxd_waddr,
   rxd_wdata,
   rxs_raddr,
   rxs_rden,
   rxs_rdata,
   rxs_wren,
   rxs_waddr,
   rxs_wdata,
   rxp_raddr,
   rxp_rden,
   rxp_rdata,
   rxp_wren,
   rxp_waddr,
   rxp_wdata,
   txd_raddr,
   txd_rden,
   txd_rdata,
   txd_recc,
   txd_wren,
   txd_waddr,
   txd_wdata,
   txs_raddr,
   txs_rden,
   txs_rdata,
   txs_wren,
   txs_waddr,
   txs_wdata);  

// Common Reset Signals
// --------------------

input   reset_reg_clk;                          //  Asynchronous Reset - reg_clk Domain

// MAC Reset Signals
// -----------------

input   mac_reset_ref_clk;                      //  Asynchronous Reset - MAC rx_clk / tx_clk Domain
input   mac_reset_ff_rx_clk;                    //  Asynchronous Reset - MAC mac_reset_ff_rx_clk Domain
input   mac_reset_ff_tx_clk;                    //  Asynchronous Reset - MAC mac_reset_ff_tx_clk Domain
   
// 40Geth PCS Reset Signals
// ------------------------

input   [3:0] xlaui_reset_rx_clk;               //  Asynchronous Reset - 40Geth PCS rx_clk Domains
input   xlaui_reset_tx_clk;                     //  Asynchronous Reset - 40Geth PCS tx_clk Domain
input   xlaui_reset_ref_clk;                    //  Asynchronous Reset - 40Geth PCS ref_clk Domain 

// 10Geth PCS Reset Signals
// ------------------------

input   [3:0] xaui_reset_rx_clk;                //  Asynchronous Reset - 10Geth PCS rxclk Domains
input   xaui_reset_tx_clk;                      //  Asynchronous Reset - 10Geth PCS txclk Domain

// Common Clock Signals
// --------------------

input   reg_clk;                                //  Regsiter Interface Clock
input   ref_clk;                                //  Reference Clock - Connected to tx_clk in XAUI mode
input   [3:0] rx_clk;                           //  Receive Line Clocks
input   tx_clk;                                 //  Transmit Line Clock
input   ff_rx_clk;                              //  Receive Client Clock
input   ff_tx_clk;                              //  Transmit Client Clock

// Serdes Interface
// ----------------

output  [19:0] sd0_tx;                          //  Transmit SERDES Lane 0
output  [19:0] sd1_tx;                          //  Transmit SERDES Lane 1
output  [19:0] sd2_tx;                          //  Transmit SERDES Lane 2
output  [19:0] sd3_tx;                          //  Transmit SERDES Lane 3
input   [19:0] sd0_rx;                          //  Receive SERDES Lane 0
input   [19:0] sd1_rx;                          //  Receive SERDES Lane 1
input   [19:0] sd2_rx;                          //  Receive SERDES Lane 2
input   [19:0] sd3_rx;                          //  Receive SERDES Lane 3
input   [3:0] sd_signal;                        //  SERDES Status        

// Client Interface
// ----------------

  // TX Application interface
  // ------------------------

input   axi_ttvalid;                            //  tVALID -> valid transaction
input   axi_ttlast;                             //  tVALID -> last transaction for a frame
input   [7:0] axi_ttkeep;                       //  tKEEP  -> valid byte qualifier, 1 bit per byte in tdata
input   [63:0] axi_ttdata;                      //  tDATA  -> frame data, left aligned
input   [6:0] axi_ttuser;                       //  tUSER  -> sideband data. 
output  axi_ttready;                            //  tREADY -> interface backpressure

  // RX Application interface
  // ------------------------
  
output  axi_rtvalid;                            //  tVALID -> valid transaction
output  axi_rtlast;                             //  tVALID -> last transaction for a frame
output  [7:0] axi_rtkeep;                       //  tKEEP  -> valid byte qualifier, 1 bit per byte in tdata
output  [63:0] axi_rtdata;                      //  tDATA  -> frame data, left aligned
output  [90-1:0] axi_rtuser;                    //  tUSER  -> sideband data. 
input   axi_rtready;                            //  tREADY -> interface backpressure

  // Other FIFO related status
  // -------------------------
        
output  tx_ovr_err;                             //  FIFO overflow truncation occured
output  tx_underflow;                           //  FIFO Underflow (tx_clk)
output  tx_empty;                               //  TX FIFO empty (tx_clk)
output  ff_rx_empty;                            //  FIFO has no data

// Mode Selection
// --------------

input   ena_40g;                                //  Enable 40Geth Mode
input   jumbo_en;                               //  Increase thresholds to support jumbo frames - XAUI only

// MAC Command and Control
// -----------------------

input   lpi_txhold;                             //  Request MAC to hold transmit (not serving FIFO, transmit idle)
output  loc_fault;                              //  RX receives LF sequences
output  rem_fault;                              //  RX receives RF sequences
output  li_fault;                               //  RX receives LinkInterruption sequences
input   tx_loc_fault;                           //  Force RS TX to send LF sequences
input   tx_rem_fault;                           //  Force RS TX to send RF sequences
input   tx_li_fault;                            //  Force RS TX to send LinkInterruption sequences
output  phy_txena;                              //  PHY Transmit Enable
output  loop_ena;                               //  PHY Loopback Command
output  pfc_mode;                               //  Priority flow control enabled (from config)
output  [7:0] pause_on;                         //  Received Flow Control Status
input   [7:0] xoff_gen;                         //  Transmit Flow Control Generate

// Timestamping Control
// --------------------

output  tx_sfd_o;                               //  SFD sent in TX
input   [64-1:0] frc_in_tx;                     //  captured time synchronous to tx clock domain
output  rx_sfd_o;                               //  SFD detected in RX
input   [64-1:0] frc_in_rx;                     //  captured time synchronous to rx clock domain
output  xgmii_rx_sop_shift;                     //  XGMII 4-Byte Column Shift of SOP     
output  xgmii_tx_sop_shift;                     //  XGMII 4-Byte Column Shift of SOP 

// Timestamp Return Interface
// --------------------------

output  tx_ts_val;                              //  tx_ts_xxx valid indication (ff_tx_clk)
output  [64-1:0] tx_ts;                         //  Transmit timestamp (ff_tx_clk)
output  [4-1:0] tx_ts_id;                       //  Frame identifier (ff_tx_clk)
output  tx_ts_frm_out;                          //  Transmit Timestamp Frame (ff_tx_clk)

// XAUI PCS Status
// ---------------

output  x_align_done;                           //  Lane Alignment Done
output  [3:0] x_disp_err;                       //  Disparity Error Indication
output  [3:0] x_char_err;                       //  Character Error Indication
output  [3:0] x_sync;                           //  Channel Synchronization Indication
output  [3:0] x_pat;                            //  Comma Detected Indication
output  [3:0] x_cg_align;                       //  Code Group Alignment Indication

// XLAUI PCS Status
// ----------------

output  xl_ber_timer_done;                      //  Hi BER measure window
output  [3:0] xl_block_lock;                    //  Block lock state reached
output  xl_align_done;                          //  Alignment marker lock state reached
output  xl_hi_ber;                              //  High Bit Error

// MAC Register Interface
// ----------------------

input   regm_rden;                              //  Register Read Strobe
input   regm_wren;                              //  Register Write Strobe
input   [7:0] regm_addr;                        //  Register Address (32-bit words)
input   [31:0] regm_din;                        //  Write Data for Host Bus
output  [31:0] regm_dout;                       //  Read Data to Host Bus
output  regm_busy;                              //  Interface Busy
output  regm_ts_avail;                          //  ts_avail status bit
output  regm_lowp;                              //  Low Power Indication
input   regm_lowp_ena;                          //  Low Power Generation

// 40Geth PCS Register Interface
// -----------------------------

input   regxl_rden;                             //  Register Read Strobe
input   regxl_wren;                             //  Register Write Strobe
input   [15:0] regxl_addr;                      //  Register Address (32-bit words)
input   [15:0] regxl_din;                       //  Write Data for Host Bus
output  [15:0] regxl_dout;                      //  Read Data to Host Bus
output  regxl_busy;                             //  Interface Busy

// 10Geth PCS Register Interface
// -----------------------------

input   regx_rden;                              //  Register Read Strobe
input   regx_wren;                              //  Register Write Strobe
input   [15:0] regx_addr;                       //  Register Address (32-bit words)
input   [15:0] regx_din;                        //  Write Data for Host Bus
output  [15:0] regx_dout;                       //  Read Data to Host Bus
output  regx_busy;                              //  Interface Busy

//  MDIO Master
//  -----------

output  mdc;                                    //  Clock                   
input   mdio_in;                                //  Data Bus In                         
output  mdio_out;                               //  Data Bus Out                        
output  mdio_oen;                               //  Data Bus Output Enable

//  Memory Interfaces
//  -----------------

output  [6-1:0] rstm_raddr;                     //  Stats RX mem Read address (rxclk)
output  rstm_rden;                              //  Stats RX mem read enable (rxclk)
input   [64:0] rstm_rdata;                      //  Stats RX mem Read data (rxclk)
output  rstm_wren;                              //  Stats RX mem write (rxclk)
output  [6-1:0] rstm_waddr;                     //  Stats RX mem write address (rxclk)
output  [64:0] rstm_wdata;                      //  Stats RX mem write data (rxclk)
output  [6-1:0] tstm_raddr;                     //  Stats TX mem Read address (txclk)
output  tstm_rden;                              //  Stats TX mem read enable (txclk)
input   [64:0] tstm_rdata;                      //  Stats TX mem Read data (txclk)
output  tstm_wren;                              //  Stats TX mem write (txclk)
output  [6-1:0] tstm_waddr;                     //  Stats TX mem write address (txclk)
output  [64:0] tstm_wdata;                      //  Stats TX mem write data (txclk)

output  [5-1:0] rxd_raddr;                      //  RX Data FIFO read address (ff_rx_clk)
output  rxd_rden;                               //  RX Data FIFO read enable (ff_rx_clk)
input   [64-1:0] rxd_rdata;                     //  RX Data FIFO read data (ff_rx_clk)
input   rxd_recc;                               //  RX Data FIFO read data ecc error (ff_rx_clk)
output  rxd_wren;                               //  RX Data FIFO write (rx_clk)
output  [5-1:0] rxd_waddr;                      //  RX Data FIFO write address (rx_clk)
output  [64-1:0] rxd_wdata;                     //  RX Data FIFO write data (rx_clk)
output  [5-1:0] rxs_raddr;                      //  RX Status read address (ff_rx_clk)
output  rxs_rden;                               //  RX Status read enable (ff_rx_clk)
input   [42-1:0] rxs_rdata;                     //  RX Status read data (ff_rx_clk)
output  rxs_wren;                               //  RX Status write (rx_clk)
output  [5-1:0] rxs_waddr;                      //  RX Status write address (rx_clk)
output  [42-1:0] rxs_wdata;                     //  RX Status write data (rx_clk)
output  [5-1:0] rxp_raddr;                      //  RX Ts/Prb read address (ff_rx_clk)
output  rxp_rden;                               //  RX Ts/Prb read enable (ff_rx_clk)
input   [64-1:0] rxp_rdata;                     //  RX Ts/Prb read data (ff_rx_clk)
output  rxp_wren;                               //  RX Ts/Prb write (rx_clk)
output  [5-1:0] rxp_waddr;                      //  RX Ts/Prb write address (rx_clk)
output  [64-1:0] rxp_wdata;                     //  RX Ts/Prb write data (rx_clk)
output  [5-1:0] txd_raddr;                      //  TX Read address (tx_clk)
output  txd_rden;                               //  TX read enable (tx_clk)
input   [66-1:0] txd_rdata;                     //  TX Read data (tx_clk)
input   txd_recc;                               //  TX Read data ecc error (tx_clk)
output  txd_wren;                               //  TX write (ff_tx_clk)
output  [5-1:0] txd_waddr;                      //  TX write addres (ff_tx_clk)
output  [66-1:0] txd_wdata;                     //  TX write data (ff_tx_clk)
output  [5-1:0] txs_raddr;                      //  TX Status Read address (tx_clk)
output  txs_rden;                               //  TX Status read enable (tx_clk)
input   [23-1:0] txs_rdata;                     //  TX Status Read data (tx_clk)
output  txs_wren;                               //  TX Status write (ff_tx_clk)
output  [5-1:0] txs_waddr;                      //  TX Status write addres (ff_tx_clk)
output  [23-1:0] txs_wdata;                     //  TX Status write data (ff_tx_clk)

//  FIFO Interface
//  --------------

wire    [6:0] ff_tx_user;                       //  Tx Commands Bit
wire    [63:0] ff_tx_data;                      //  Data Out
wire    ff_tx_sop;                              //  Start of Packet
wire    ff_tx_eop;                              //  End of Packet
wire    [2:0] ff_tx_mod;                        //  Last Word Modulo
wire    ff_tx_err;                              //  Errored Packet
wire    ff_tx_err_int;                          //  Errored Packet
wire    ff_tx_axi_err;                          //  Errored Packet 
wire    ff_tx_crc;                              //  Append CRC on transmit
wire    ff_tx_wren;                             //  Write Enable
wire    ff_tx_rdy;                              //  FIFO Ready
wire    ff_tx_rdy_int;                          //  Almost full, fifo ready
wire    ff_tx_septy;                            //  Section Empty in Transmit FIFO
wire    [4-1:0] ff_tx_id;                       //  TX frame identifier
wire    ff_tx_ts_frm;                           //  mark frame for timestamp storage
wire    [63:0] ff_rx_data;                      //  Data Out
wire    ff_rx_sop;                              //  Start of Packet
wire    ff_rx_eop;                              //  End of Packet
wire    [2:0] ff_rx_mod;                        //  Last Word Modulo
wire    ff_rx_err;                              //  Errored Packet indication
wire    [25-1:0] ff_rx_err_stat;                //  Errored Packet Status Word
wire    ff_rx_rdy;                              //  PHY Application Ready
wire    ff_rx_dval;                             //  Data Valid Strobe
wire    [64-1:0] ff_rx_ts;                      //  Receive Timestamp

//  MAC XGMII / XLGMII Interface
//  ----------------------------

wire    [7:0] mac_xlgmii_rxc;                   //  X/XLGMII Receive control
wire    [63:0] mac_xlgmii_rxd;                  //  X/XLGMII Receive data
wire    mac_xlgmii_rx_ena;                      //  X/LGMII Receive clock enable 
wire    mac_xlgmii_rxt0_next;                   //  X/LGMII Advance indication of TERM block without data                    
wire    mac_xlgmii_tx_ena;                      //  X/LGMII Transmit clock enable
wire    [7:0] mac_xlgmii_txc;                   //  X/XLGMII transmit control
wire    [63:0] mac_xlgmii_txd;                  //  X/XLGMII transmit data

//  XAUI PCS XGMII Interface
//  ------------------------

wire    [7:0] x_xgmii_rxc;                      //  XGMII Receive control
wire    [63:0] x_xgmii_rxd;                     //  XGMII Receive data
wire    [7:0] x_xgmii_rxc_r;                    //  XGMII Receive control
wire    [63:0] x_xgmii_rxd_r;                   //  XGMII Receive data
wire    x_xgmii_rxt0_next;                      //  XGMII Advance indication of TERM block without data                           

//  XLAUI PCS XGMII Interface
//  -------------------------

wire    [7:0] xl_xgmii_rxc;                     //  XLGMII Receive control
wire    [63:0] xl_xgmii_rxd;                    //  XLGMII Receive data
wire    xl_xgmii_rx_ena;                        //  XLGMII Receive clock enable 
wire    xl_xgmii_rxt0_next;                     //  XLGMII Advance indication of TERM block without data                           
wire    xl_xgmii_tx_ena;                        //  XLGMII Transmit clock enable 

//  XAUI PCS Transmit Interface
//  ---------------------------

wire    [19:0] xaui_sd0_tx;                     //  Transmit SERDES Lane 0
wire    [19:0] xaui_sd1_tx;                     //  Transmit SERDES Lane 1
wire    [19:0] xaui_sd2_tx;                     //  Transmit SERDES Lane 2
wire    [19:0] xaui_sd3_tx;                     //  Transmit SERDES Lane 3

//  MAC Signals
//  -----------

wire    phy_los;                                //  PHY loss of signal status

//  XLAUI PCS Transmit Interface
//  ----------------------------

wire    [19:0] xlaui_sd0_tx;                    //  Transmit SERDES Lane 0
wire    [19:0] xlaui_sd1_tx;                    //  Transmit SERDES Lane 1
wire    [19:0] xlaui_sd2_tx;                    //  Transmit SERDES Lane 2
wire    [19:0] xlaui_sd3_tx;                    //  Transmit SERDES Lane 3

//  Clock Domain Crossing
//  ---------------------

wire    ena_40g_ref;
wire    ena_40g_txsd;
wire    [3:0] sd_signal_srxsd;  
wire    x_align_done_s;
wire    [3:0] x_disp_err_s;
wire    [3:0] x_char_err_s;
wire    [3:0] x_sync_s;
wire    [3:0] x_pat_s;
wire    [3:0] x_cg_align_s;

mtip_xsync #(22) U_SREF (

   .data_in({x_cg_align_s, x_pat_s, x_sync_s, x_char_err_s, 
             x_disp_err_s, x_align_done_s, ena_40g}),
   .reset(mac_reset_ref_clk),
   .clk(ref_clk),
   .data_s({x_cg_align, x_pat, x_sync, x_char_err, 
            x_disp_err, x_align_done, ena_40g_ref}));
   
mtip_xsync #(1) U_STXSD (

   .data_in(ena_40g),
   .reset(xaui_reset_tx_clk),
   .clk(tx_clk),
   .data_s(ena_40g_txsd));
   
mtip_xsync #(1) U_SRXSD0 (

   .data_in(sd_signal[0]),
   .reset(xlaui_reset_rx_clk[0]),
   .clk(rx_clk[0]),
   .data_s(sd_signal_srxsd[0]));

mtip_xsync #(1) U_SRXSD1 (

   .data_in(sd_signal[1]),
   .reset(xlaui_reset_rx_clk[1]),
   .clk(rx_clk[1]),
   .data_s(sd_signal_srxsd[1]));
   
mtip_xsync #(1) U_SRXSD2 (

   .data_in(sd_signal[2]),
   .reset(xlaui_reset_rx_clk[2]),
   .clk(rx_clk[2]),
   .data_s(sd_signal_srxsd[2]));
   
mtip_xsync #(1) U_SRXSD3 (

   .data_in(sd_signal[3]),
   .reset(xlaui_reset_rx_clk[3]),
   .clk(rx_clk[3]),
   .data_s(sd_signal_srxsd[3]));
   
top_xgxs_w_host U_XAUI (

   .reset_sd0_rx_clk(xaui_reset_rx_clk[0]),
   .reset_sd1_rx_clk(xaui_reset_rx_clk[1]),
   .reset_sd2_rx_clk(xaui_reset_rx_clk[2]),
   .reset_sd3_rx_clk(xaui_reset_rx_clk[3]),
   .reset_xgmii_txclk(xaui_reset_tx_clk),
   .reset_xgmii_rxclk(xaui_reset_rx_clk[0]),
   .xgmii_txclk(ref_clk),
   .xgmii_rxclk(ref_clk),
   .xgmii_txd(mac_xlgmii_txd),
   .xgmii_txc(mac_xlgmii_txc),
   .xgmii_rxd(x_xgmii_rxd),
   .xgmii_rxc(x_xgmii_rxc),
   .sd0_tx(xaui_sd0_tx),
   .sd1_tx(xaui_sd1_tx),
   .sd2_tx(xaui_sd2_tx),
   .sd3_tx(xaui_sd3_tx),
   .sd0_rx(sd0_rx),
   .sd0_rx_clk(rx_clk[0]),
   .sd1_rx(sd1_rx),
   .sd1_rx_clk(rx_clk[1]),  
   .sd2_rx(sd2_rx),
   .sd2_rx_clk(rx_clk[2]),  
   .sd3_rx(sd3_rx),
   .sd3_rx_clk(rx_clk[3]),  
   .sd_signal0(sd_signal_srxsd[0]),
   .sd_signal1(sd_signal_srxsd[1]),
   .sd_signal2(sd_signal_srxsd[2]),
   .sd_signal3(sd_signal_srxsd[3]),
   .jumbo_en(jumbo_en),  
   .align_done(x_align_done_s),
   .disp_err(x_disp_err_s),
   .char_err(x_char_err_s),
   .cg_align(x_cg_align_s),
   .sync(x_sync_s),
   .pat(x_pat_s),
   .match_fault(),   
   .reset_reg_clk(reset_reg_clk),
   .reg_clk(reg_clk),
   .reg_rd(regx_rden),
   .reg_wr(regx_wren),
   .reg_addr(regx_addr),
   .reg_din(regx_din),
   .reg_dout(regx_dout),
   .reg_busy(regx_busy));
   
mtip_dffvec_ena #(64+8) U_XGDLY (

   .reset(xaui_reset_rx_clk[0]),
   .clk(ref_clk),
   .ena (1'b 1),
   .i({x_xgmii_rxc,    x_xgmii_rxd}),
   .o ({x_xgmii_rxc_r, x_xgmii_rxd_r}));
        
assign  x_xgmii_rxt0_next = (x_xgmii_rxc[0] == 1'b 1 && x_xgmii_rxd[7:0] == 8'h FD) ? 1'b 1 : 1'b 0;
   
eth40g_pcs64_ll_top U_XLAUI (

   .ref_clk(ref_clk),
   .reset_ref_clk(xlaui_reset_ref_clk),
   .reg_clk(reg_clk),        
   .reset_reg_clk(reset_reg_clk),        
   .sd_tx_clk({4{tx_clk}}),
   .reset_sd_tx_clk({4{xlaui_reset_tx_clk}}),               
   .sd_rx_clk(rx_clk),        
   .reset_sd_rx_clk(xlaui_reset_rx_clk),
   .cgmii_txc(mac_xlgmii_txc),
   .cgmii_txd(mac_xlgmii_txd),
   .cgmii_txclk_ena(xl_xgmii_tx_ena),
   .sd0_rx(sd0_rx),
   .sd1_rx(sd1_rx),
   .sd2_rx(sd2_rx),
   .sd3_rx(sd3_rx),
   .signal_det(sd_signal_srxsd),
   .sd0_tx(xlaui_sd0_tx),
   .sd1_tx(xlaui_sd1_tx),
   .sd2_tx(xlaui_sd2_tx),
   .sd3_tx(xlaui_sd3_tx),
   .cgmii_rxc(xl_xgmii_rxc),
   .cgmii_rxd(xl_xgmii_rxd),
   .xlgmii_rxt0_next(xl_xgmii_rxt0_next),
   .cgmii_rxclk_ena(xl_xgmii_rx_ena),
   .ber_timer_done(xl_ber_timer_done),
   .block_lock(xl_block_lock),
   .align_done(xl_align_done),
   .hi_ber(xl_hi_ber),
   .reg_rden(regxl_rden),
   .reg_wren(regxl_wren),
   .reg_addr(regxl_addr),
   .reg_din(regxl_din),
   .reg_dout(regxl_dout),
   .reg_busy(regxl_busy));

//  X/XLGMII Mux
//  ------------

assign mac_xlgmii_tx_ena    = (ena_40g_ref==1'b 1) ? xl_xgmii_tx_ena    : 1'b 1;
assign mac_xlgmii_rx_ena    = (ena_40g_ref==1'b 1) ? xl_xgmii_rx_ena    : 1'b 1;
assign mac_xlgmii_rxc       = (ena_40g_ref==1'b 1) ? xl_xgmii_rxc       : x_xgmii_rxc_r;
assign mac_xlgmii_rxd       = (ena_40g_ref==1'b 1) ? xl_xgmii_rxd       : x_xgmii_rxd_r;
assign mac_xlgmii_rxt0_next = (ena_40g_ref==1'b 1) ? xl_xgmii_rxt0_next : x_xgmii_rxt0_next;

//  Serdes Mux
//  ----------

assign sd0_tx = (ena_40g_txsd==1'b 0) ? xaui_sd0_tx : xlaui_sd0_tx;
assign sd1_tx = (ena_40g_txsd==1'b 0) ? xaui_sd1_tx : xlaui_sd1_tx;
assign sd2_tx = (ena_40g_txsd==1'b 0) ? xaui_sd2_tx : xlaui_sd2_tx;
assign sd3_tx = (ena_40g_txsd==1'b 0) ? xaui_sd3_tx : xlaui_sd3_tx;

//  PHY Status
//  ----------

assign phy_los = (sd_signal==4'b 1111) ? 1'b 0 : 1'b 1;

top_xlgmac_64 U_MAC (

   .reset_reg_clk(reset_reg_clk),
   .reset_rxclk(mac_reset_ref_clk),
   .reset_txclk(mac_reset_ref_clk),
   .reset_ff_rx_clk(mac_reset_ff_rx_clk),
   .reset_ff_tx_clk(mac_reset_ff_tx_clk),
   .reg_clk(reg_clk),
   .reg_rden(regm_rden),
   .reg_wren(regm_wren),
   .reg_addr(regm_addr),
   .reg_data_in(regm_din),
   .reg_data_out(regm_dout),
   .reg_busy(regm_busy),
   .reg_ts_avail(regm_ts_avail),
   .reg_lowp(regm_lowp),
   .reg_lowp_ena(regm_lowp_ena),
   .lpi_txhold(lpi_txhold),
   .mdc(mdc),
   .mdio_in(mdio_in),
   .mdio_out(mdio_out),
   .mdio_oen(mdio_oen),
   .loc_fault(loc_fault),
   .rem_fault(rem_fault),
   .li_fault(li_fault),
   .tx_loc_fault(tx_loc_fault),
   .tx_rem_fault(tx_rem_fault),
   .tx_li_fault(tx_li_fault),
   .phy_txena(phy_txena),
   .phy_los(phy_los),
   .loop_ena(loop_ena),
   .pfc_mode(pfc_mode),
   .pause_on(pause_on),
   .xoff_gen(xoff_gen),
   .tx_sfd_o(tx_sfd_o),
   .frc_in_tx(frc_in_tx),
   .rx_sfd_o(rx_sfd_o),
   .frc_in_rx(frc_in_rx),
   .xgmii_rx_sop_shift(xgmii_rx_sop_shift),
   .xgmii_tx_sop_shift(xgmii_tx_sop_shift),   
   .tx_clk(ref_clk),
   .rx_clk(ref_clk),
   .xlgmii_txclk_ena(mac_xlgmii_tx_ena),
   .xlgmii_rxclk_ena(mac_xlgmii_rx_ena),
   .xlgmii_rxc(mac_xlgmii_rxc),
   .xlgmii_rxd(mac_xlgmii_rxd),
   .xlgmii_rxt0_next(mac_xlgmii_rxt0_next),
   .xlgmii_txc(mac_xlgmii_txc),
   .xlgmii_txd(mac_xlgmii_txd),
   .ff_tx_clk(ff_tx_clk),
   .ff_tx_data(ff_tx_data),
   .ff_tx_sop(ff_tx_sop),
   .ff_tx_eop(ff_tx_eop),
   .ff_tx_mod(ff_tx_mod),
   .ff_tx_err(ff_tx_err),
   .ff_tx_crc(ff_tx_crc),
   .ff_tx_wren(ff_tx_wren),
   .ff_tx_rdy(ff_tx_rdy),
   .ff_tx_septy(ff_tx_septy),
   .ff_tx_id(ff_tx_id),
   .ff_tx_ts_frm(ff_tx_ts_frm),
   .ff_rx_clk(ff_rx_clk),
   .ff_rx_data(ff_rx_data),
   .ff_rx_sop(ff_rx_sop),
   .ff_rx_eop(ff_rx_eop),
   .ff_rx_mod(ff_rx_mod),
   .ff_rx_err(ff_rx_err),
   .ff_rx_err_stat(ff_rx_err_stat),
   .ff_rx_rdy(ff_rx_rdy),
   .ff_rx_dval(ff_rx_dval),
   .ff_rx_dsav(),
   .ff_rx_ts(ff_rx_ts),
   .ff_rx_empty(ff_rx_empty),
   .tx_ovr_err(tx_ovr_err),
   .tx_underflow(tx_underflow),
   .tx_empty(tx_empty),
   .tx_ts_val(tx_ts_val),
   .tx_ts(tx_ts),
   .tx_ts_id(tx_ts_id),
   .tx_ts_frm_out(tx_ts_frm_out),
   .rstm_raddr(rstm_raddr),
   .rstm_rden(rstm_rden),
   .rstm_rdata(rstm_rdata),
   .rstm_wren(rstm_wren),
   .rstm_waddr(rstm_waddr),
   .rstm_wdata(rstm_wdata),
   .tstm_raddr(tstm_raddr),
   .tstm_rden(tstm_rden),
   .tstm_rdata(tstm_rdata),
   .tstm_wren(tstm_wren),
   .tstm_waddr(tstm_waddr),
   .tstm_wdata(tstm_wdata),
   .rxd_raddr(rxd_raddr),
   .rxd_rden(rxd_rden),
   .rxd_rdata(rxd_rdata),
   .rxd_recc(rxd_recc),
   .rxd_wren(rxd_wren),
   .rxd_waddr(rxd_waddr),
   .rxd_wdata(rxd_wdata),
   .rxs_raddr(rxs_raddr),
   .rxs_rden(rxs_rden),
   .rxs_rdata(rxs_rdata),
   .rxs_wren(rxs_wren),
   .rxs_waddr(rxs_waddr),
   .rxs_wdata(rxs_wdata),
   .rxp_raddr(rxp_raddr),
   .rxp_rden(rxp_rden),
   .rxp_rdata(rxp_rdata),
   .rxp_wren(rxp_wren),
   .rxp_waddr(rxp_waddr),
   .rxp_wdata(rxp_wdata),
   .txd_raddr(txd_raddr),
   .txd_rden(txd_rden),
   .txd_rdata(txd_rdata),
   .txd_recc(txd_recc),
   .txd_wren(txd_wren),
   .txd_waddr(txd_waddr),
   .txd_wdata(txd_wdata),
   .txs_raddr(txs_raddr),
   .txs_rden(txs_rden),
   .txs_rdata(txs_rdata),
   .txs_wren(txs_wren),
   .txs_waddr(txs_waddr),
   .txs_wdata(txs_wdata));
   
assign ff_tx_rdy_int = ff_tx_rdy & ff_tx_septy;

tx_axi4s_ff #(

        .FLOP_INPUTS(1),
        .FLOP_OUTPUTS(0),
        .DATA_WIDTH(64),
        .DATA_MOD(3),
        .KEEP_WIDTH(64/8),
        .USER_WIDTH(7),
        .CFG_WRITE64_ENA(0))
        
   U_TX_AXI4S_FF (
   
        .reset(mac_reset_ff_tx_clk),
        .clk(ff_tx_clk),
        .cfg_write64(1'b 0),
        .sw_reset(1'b 0),
        .tvalid(axi_ttvalid),
        .tlast(axi_ttlast),
        .tkeep(axi_ttkeep),
        .tdata(axi_ttdata),
        .tuser(axi_ttuser),
        .tready(axi_ttready),
        .ff_tx_wren(ff_tx_wren),
        .ff_tx_sop(ff_tx_sop),
        .ff_tx_eop(ff_tx_eop),
        .ff_tx_emod(ff_tx_mod),
        .ff_tx_user(ff_tx_user),
        .ff_tx_data(ff_tx_data),
        .ff_tx_axi_err(ff_tx_axi_err),
        .ff_tx_rdy(ff_tx_rdy_int));
      
assign ff_tx_err_int = ff_tx_user[6];
assign ff_tx_crc     = ff_tx_user[5];
assign ff_tx_id      = ff_tx_user[4:1];
assign ff_tx_ts_frm  = ff_tx_user[0];
assign ff_tx_err     = ff_tx_err_int | ff_tx_axi_err;

rx_axi4s_ffmap #(

        .FLOP_INPUTS(0),
        .FLOP_OUTPUTS(1),
        .RXFIFO_RDY_DELAY(2),
        .DATA_WIDTH(64),
        .DATA_MOD(3),
        .KEEP_WIDTH(64/8),
        .USER_WIDTH(90),
        .TS_WIDTH(64),
        .RX_FF_STAT_WIDTH(25))
        
     U_RX_AXI4S_FFMAP ( 

        .reset(mac_reset_ff_rx_clk),
        .clk(ff_rx_clk),
        .cfg_write64(1'b 0),
        .sw_reset(1'b 0),
        .tvalid(axi_rtvalid),
        .tlast(axi_rtlast),
        .tkeep(axi_rtkeep),
        .tdata(axi_rtdata),
        .tuser(axi_rtuser),
        .tready(axi_rtready),
        .ff_rx_dval(ff_rx_dval),
        .ff_rx_sop(ff_rx_sop),
        .ff_rx_eop(ff_rx_eop),
        .ff_rx_emod(ff_rx_mod),
        .ff_rx_err(ff_rx_err),
        .ff_rx_err_stat(ff_rx_err_stat),
        .ff_rx_ts(ff_rx_ts),
        .ff_rx_data(ff_rx_data),
        .ff_rx_rdy(ff_rx_rdy));

endmodule
